/*
 *   Licensed to the Apache Software Foundation (ASF) under one
 *   or more contributor license agreements.  See the NOTICE file
 *   distributed with this work for additional information
 *   regarding copyright ownership.  The ASF licenses this file
 *   to you under the Apache License, Version 2.0 (the
 *   "License"); you may not use this file except in compliance
 *   with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing,
 *   software distributed under the License is distributed on an
 *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *   KIND, either express or implied.  See the License for the
 *   specific language governing permissions and limitations
 *   under the License.
 *
 */

package org.apache.directory.server.codec.json;


import java.lang.reflect.Type;

import org.apache.directory.server.codec.json.operations.add.AddRequestCodec;
import org.apache.directory.server.codec.json.operations.bind.BindRequestCodec;
import org.apache.directory.server.codec.json.operations.bind.BindResponseCodec;
import org.apache.directory.server.codec.json.operations.compare.CompareRequestCodec;
import org.apache.directory.server.codec.json.operations.delete.DeleteRequestCodec;
import org.apache.directory.server.codec.json.operations.modify.DefaultModificationCodec;
import org.apache.directory.server.codec.json.operations.modify.ModifyRequestCodec;
import org.apache.directory.server.codec.json.operations.modifydn.ModifyDnRequestCodec;
import org.apache.directory.server.codec.json.operations.search.ClonedServerEntryCodec;
import org.apache.directory.server.codec.json.operations.search.DefaultEntryCodec;
import org.apache.directory.server.codec.json.operations.search.EntryAttributeCodec;
import org.apache.directory.server.codec.json.operations.search.SearchRequestCodec;
import org.apache.directory.server.core.entry.ClonedServerEntry;
import org.apache.directory.server.core.entry.ClonedServerEntrySearch;
import org.apache.directory.shared.ldap.entry.AbstractValue;
import org.apache.directory.shared.ldap.entry.BinaryValue;
import org.apache.directory.shared.ldap.entry.DefaultEntry;
import org.apache.directory.shared.ldap.entry.DefaultEntryAttribute;
import org.apache.directory.shared.ldap.entry.DefaultModification;
import org.apache.directory.shared.ldap.entry.StringValue;
import org.apache.directory.shared.ldap.message.AbstractResultResponse;
import org.apache.directory.shared.ldap.message.AddRequestImpl;
import org.apache.directory.shared.ldap.message.BindRequestImpl;
import org.apache.directory.shared.ldap.message.BindResponseImpl;
import org.apache.directory.shared.ldap.message.CompareRequestImpl;
import org.apache.directory.shared.ldap.message.DeleteRequestImpl;
import org.apache.directory.shared.ldap.message.LdapResultImpl;
import org.apache.directory.shared.ldap.message.ModifyDnRequestImpl;
import org.apache.directory.shared.ldap.message.ModifyRequestImpl;
import org.apache.directory.shared.ldap.message.SearchRequestImpl;
import org.apache.directory.shared.ldap.name.DN;
import org.apache.directory.shared.ldap.schema.SchemaManager;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;


/**
 * TODO JsonBuilder.
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class JsonBuilder
{

    private static final GsonBuilder BUILDER = new GsonBuilder();
    private static Gson gson;

    private static SchemaManager schemaManager;

    static
    {
        BUILDER.registerTypeAdapter( BindResponseImpl.class, new BindResponseCodec() );
        BUILDER.registerTypeAdapter( BindRequestImpl.class, new BindRequestCodec() );

        BUILDER.registerTypeAdapter( AddRequestImpl.class, new AddRequestCodec() );
        BUILDER.registerTypeAdapter( DeleteRequestImpl.class, new DeleteRequestCodec() );
        BUILDER.registerTypeAdapter( SearchRequestImpl.class, new SearchRequestCodec() );
        BUILDER.registerTypeAdapter( ModifyRequestImpl.class, new ModifyRequestCodec() );
        BUILDER.registerTypeAdapter( ModifyDnRequestImpl.class, new ModifyDnRequestCodec() );
        BUILDER.registerTypeAdapter( CompareRequestImpl.class, new CompareRequestCodec() );

        BUILDER.registerTypeAdapter( LdapResultImpl.class, new LdapResultCodec() );
        BUILDER.registerTypeAdapter( DN.class, new DnCodec() );
        BUILDER.registerTypeAdapter( DefaultEntryAttribute.class, new EntryAttributeCodec() );
        BUILDER.registerTypeAdapter( DefaultEntry.class, new DefaultEntryCodec() );
        BUILDER.registerTypeAdapter( ClonedServerEntry.class, new ClonedServerEntryCodec() );
        BUILDER.registerTypeAdapter( ClonedServerEntrySearch.class, new ClonedServerEntryCodec() );
        BUILDER.registerTypeAdapter( DefaultModification.class, new DefaultModificationCodec() );
        BUILDER.registerTypeAdapter( AbstractResultResponse.class, new AbstractResultResponseCodec() );
        BUILDER.registerTypeAdapter( StringValue.class, new ValueCodec() );
        BUILDER.registerTypeAdapter( BinaryValue.class, new ValueCodec() );
        BUILDER.registerTypeAdapter( AbstractValue.class, new ValueCodec() );
        
        gson = BUILDER.create();
    }


    public static <T> T fromJson( String json, Class<T> classOfT ) throws JsonParseException
    {
        return gson.fromJson( json, classOfT );
    }


    public static <T> T fromJson( JsonElement json, Class<T> classOfT ) throws JsonParseException
    {
        return gson.fromJson( json, classOfT );
    }


    public static JsonElement toJsonTree( Object src )
    {
        return gson.toJsonTree( src );
    }


    public static String toJson( Object src, Type typeOfSrc )
    {
        return gson.toJson( src, typeOfSrc );
    }


    public static String toJson( Object src )
    {
        return gson.toJson( src );
    }

    public static DN decodeDn( String jsonDn )
    {
        return gson.fromJson( jsonDn, DN.class );
    }

    public static DN decodeDn( JsonElement jsonDn )
    {
        return gson.fromJson( jsonDn, DN.class );
    }

    
    public static Gson get()
    {
        return gson;
    }


    public static SchemaManager getSchemaManager()
    {
        return schemaManager;
    }


    public static void setSchemaManager( SchemaManager schemaManager )
    {
        JsonBuilder.schemaManager = schemaManager;
    }

}
